﻿/**
 * Peter
 * Created by: Peter Development Team
 *    http://peter.codeplex.com/
 * 
 * GNU General Public License version 2 (GPLv2)
 *    http://peter.codeplex.com/license
 *
 *  This code is provided on an AS IS basis, with no WARRANTIES,
 *  CONDITIONS or GUARANTEES of any kind.
 *  
 **/

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using CWDev.SLNTools.Core;
using Peter.Common;
using Peter.Common.Code;
using Peter.Common.MainMenu;
using Peter.Common.Tree;
using Peter.Net.CodeCompletion;

namespace Peter.Net
{
   /// <summary>
   /// Represents a .net solution.
   /// </summary>
   public class SolutionProject : PeterProjectItem
   {
      private SolutionFile m_SolutionFile;
      private readonly Dispatcher m_Dispatcher;

      /// <summary>
      /// Initializes a new peter project.
      /// </summary>
      /// <param name="projectPath"></param>
      public SolutionProject (string projectPath) : base (null, new FileInfo (projectPath))
      {
         this.m_Dispatcher = Dispatcher.CurrentDispatcher;
         this.CodeCompletion = new CSharpCodeCompletion();
      }

      /// <summary>
      /// Gets the code completion for the entire solution.
      /// </summary>
      public new BaseCodeCompletion CodeCompletion { get; private set; }

      /// <summary>
      /// Gets the folder the solution is located in.
      /// </summary>
      public string SolutionDirectory { get; private set; }

      /// <summary>
      /// Opens the given project
      /// </summary>
      /// <returns>True if opened successfully, otherwise false.</returns>
      public async Task<bool> Open ()
      {
         try
         {
            var projectPath = this.File.FullName;
            this.m_SolutionFile = SolutionFile.FromFile (this.File.FullName);
            this.Icon = MainMenuIcon.Radiobutton;
            this.IconBrush = Brushes.Purple;
            this.IconMargin = new Thickness(0,0,3,0);
            this.SolutionDirectory = projectPath.Substring (0, projectPath.LastIndexOf ('\\') + 1);
            this.Text = projectPath.Substring (projectPath.LastIndexOf('\\') + 1).Replace(".sln", "");
            foreach (var project in this.m_SolutionFile.Projects.OrderBy (p => p.ProjectName))
               await this.AddProject(this, project);
         }
         catch (Exception ex)
         {
            Console.Error.WriteLine(ex.Message);
            return false;
         }
         return true;
      }

      private async Task AddProject (ModelTreeViewItem parent, Project project)
      {
         if (project.ProjectTypeGuid == KnownProjectTypeGuid.SolutionFolder)
         {
            if (parent == this && project.ParentFolder != null) return;
            var folder = new SolutionFolder (parent, project.ProjectName);
            foreach (var child in project.Childs.OrderBy(p => p.ProjectName))
               await this.AddProject(folder, child);
            foreach (var projectSection in project.ProjectSections)
            {
               foreach (var propertyLine in projectSection.PropertyLines)
                  folder.Children.Add (new PeterProjectItem (folder, new FileInfo (this.SolutionDirectory + propertyLine.Name)));
            }
            parent.Children.Insert (0, folder);
         }
         else
         {
            if (parent == this && project.ParentFolder != null) return;
            var csProj = new CSharpProject (parent, this, project);
            parent.Children.Add (csProj);
            await csProj.Open ();
         }
      }

      /// <summary>
      /// Occurs when the Peter application is closing.
      /// </summary>
      public override void PeterClosing ()
      {
         foreach (var child in this.Children.Cast<PeterProjectItem>())
         {
            child.PeterClosing ();
         }
      }

      /// <summary>
      /// Sets if this is the current project or not.
      /// </summary>
      /// <param name="isCurrent">True if current, false if removing current flag.</param>
      public override void SetCurrentProject (bool isCurrent)
      {
         base.SetCurrentProject (isCurrent);
         if (!isCurrent)
         {
            foreach (var child in this.Children)
            {
               var project = child as PeterProjectItem;
               if (project != null)
                  project.SetCurrentProject (false);
            }
         }
      }
   }
}
